/*    
	AC101 Codec driver library example.
	Uses the ESP32-A1S module with integrated AC101 codec, mounted on the ESP32 Audio Kit board:
	https://wiki.ai-thinker.com/esp32-audio-kit

	Required library: ESP8266Audio https://github.com/earlephilhower/ESP8266Audio

	Copyright (C) 2019, Ivo Pullens, Emmission
	
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "music.h"

#include "AudioFileSourceSD.h"
// #include "AudioFileSourcePROGMEM.h"
// #include "AudioGeneratorRTTTL.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2S.h"
#include "AC101.h"
#include "FS.h"
#include "SD.h"


#define MAX_PLAY_FILE_NUM 20
 char musicfiles[MAX_PLAY_FILE_NUM][20]={};
static uint8_t musicfiles_cnt=0;
static uint8_t current=0;
static void printDirectory(File dir, int numTabs) ;


const char song[] PROGMEM = 
"Batman:d=8,o=5,b=180:d,d,c#,c#,c,c,c#,c#,d,d,c#,c#,c,c,c#,c#,d,d#,c,c#,c,c,c#,c#,f,p,4f";
// Plenty more at: http://mines.lumpylumpy.com/Electronics/Computers/Software/Cpp/MFC/RingTones.RTTTL

AudioGeneratorMP3 *mp3;
// AudioGeneratorRTTTL *rtttl;
// AudioFileSourcePROGMEM *file;
AudioFileSourceSD *file;
AudioOutputI2S *out;

#define IIS_SCLK                    27
#define IIS_LCLK                    26
#define IIS_DSIN                    25

#define IIC_CLK                     32
#define IIC_DATA                    33

#define GPIO_PA_EN                  GPIO_NUM_21
#define GPIO_SEL_PA_EN              GPIO_SEL_21

#define PIN_PLAY                    (39)      // KEY 4
#define PIN_VOL_UP                  (34)      // KEY 5
#define PIN_VOL_DOWN                (4)       // KEY 6

static AC101 ac;
static lv_obj_t *list;
static uint8_t volume = 30;
const uint8_t volume_step = 2;



static lv_obj_t *scr;
static lv_obj_t *label_vol;
static lv_obj_t *mp3_current;
static lv_obj_t *mp3_next;
static lv_obj_t *mp3_prev;
void play_event(lv_obj_t *obj, lv_event_t event)
{
	if(event == LV_EVENT_CLICKED)
	{
		// if (!(mp3->isRunning()))
		// {
		// 	mp3->stop();
		// 	// Start playing
		// 	Serial.printf("Start playing\n");
		// 	file->seek(0, SEEK_SET);
		// 	mp3->begin(file, out);
		// 	lv_label_set_text(label_menu,"Start playing");
			
		// }
		// else
		{
			Serial.println(musicfiles[current]);
			file = new AudioFileSourceSD(musicfiles[current]);
			
			mp3->begin(file, out);
			Serial.printf("Use KEY4 to play, KEY5/KEY6 for volume Up/Down\n");
		}
		
	}
}

void volup_event(lv_obj_t *obj, lv_event_t event)
{
	if(event == LV_EVENT_CLICKED)
	{
		if (volume <= (63-volume_step))
		{
			// Increase volume
			volume += volume_step;
			// Volume change requested
			Serial.printf("Volume %d\n", volume);
			ac.SetVolumeSpeaker(volume);
			ac.SetVolumeHeadphone(volume);
			char buffer_vol[4];
			snprintf(buffer_vol,sizeof(buffer_vol),"%d",volume);
			lv_label_set_text(label_vol,buffer_vol);
		} 
	}
}

void voldown_event(lv_obj_t *obj, lv_event_t event)
{
	if(event == LV_EVENT_CLICKED)
	{
		if (volume >= volume_step)
		{
			// Decrease volume
			volume -= volume_step;
			// Volume change requested
			Serial.printf("Volume %d\n", volume);
			ac.SetVolumeSpeaker(volume);
			ac.SetVolumeHeadphone(volume);
			 
			char buffer_vol[4];
			snprintf(buffer_vol,sizeof(buffer_vol),"%d",volume);
			lv_label_set_text(label_vol,buffer_vol);
			 
		} 
	}
}


static void next_event(lv_obj_t *obj, lv_event_t event)
{
	if(event == LV_EVENT_CLICKED)
	{
		 
		 
		if((current+1)<(musicfiles_cnt-1))
		{
				lv_label_set_text(mp3_prev,		musicfiles[current]);
				lv_label_set_text(mp3_current,	musicfiles[current+1]);
				lv_label_set_text(mp3_next,		musicfiles[current+2]);
				lv_obj_align(mp3_current,scr_tft,LV_ALIGN_CENTER,0,0);
				lv_obj_align(mp3_prev,mp3_current,LV_ALIGN_OUT_TOP_MID,0,0);
				lv_obj_align(mp3_next,mp3_current,LV_ALIGN_OUT_BOTTOM_MID,0,0);

				Serial.println(musicfiles[current] );
				Serial.println(musicfiles[current+1]) ;
				Serial.println(musicfiles[current+2] );
				Serial.println("------------------");
				current++;
				
		}
		else if((current+1)==(musicfiles_cnt-1))
		{
				lv_label_set_text(mp3_prev,		musicfiles[current]);
				lv_label_set_text(mp3_current,	musicfiles[current+1]);
				lv_label_set_text(mp3_next,		"");
				lv_obj_align(mp3_current,scr_tft,LV_ALIGN_CENTER,0,0);
				lv_obj_align(mp3_prev,mp3_current,LV_ALIGN_OUT_TOP_MID,0,0);
				lv_obj_align(mp3_next,mp3_current,LV_ALIGN_OUT_BOTTOM_MID,0,0);
				Serial.println(musicfiles[current] );
				Serial.println(musicfiles[current+1]) ;
				// Serial.println(musicfiles[current+2] );
				Serial.println("------------------");
				current++;
		}
		
		 
	}
}
static void prev_event(lv_obj_t *obj, lv_event_t event)
{
	if(event == LV_EVENT_CLICKED)
	{
		 		if((current)>1)
		{
				lv_label_set_text(mp3_prev,		musicfiles[current-2]);
				lv_label_set_text(mp3_current,	musicfiles[current-1]);
				lv_label_set_text(mp3_next,		musicfiles[current]);
				lv_obj_align(mp3_current,scr_tft,LV_ALIGN_CENTER,0,0);
				lv_obj_align(mp3_prev,mp3_current,LV_ALIGN_OUT_TOP_MID,0,0);
				lv_obj_align(mp3_next,mp3_current,LV_ALIGN_OUT_BOTTOM_MID,0,0);

				Serial.println(musicfiles[current-2] );
				Serial.println(musicfiles[current-1]) ;
				Serial.println(musicfiles[current] );
				Serial.println("------------------");
				current--;
				
		}
		else if((current )==1)
		{
				lv_label_set_text(mp3_prev,		"");
				lv_label_set_text(mp3_current,	musicfiles[current-1]);
				lv_label_set_text(mp3_next,		musicfiles[current]);
				lv_obj_align(mp3_current,scr_tft,LV_ALIGN_CENTER,0,0);
				lv_obj_align(mp3_prev,mp3_current,LV_ALIGN_OUT_TOP_MID,0,0);
				lv_obj_align(mp3_next,mp3_current,LV_ALIGN_OUT_BOTTOM_MID,0,0);
				Serial.println(musicfiles[current-1] );
				Serial.println(musicfiles[current]) ;
				// Serial.println(musicfiles[current+2] );
				Serial.println("------------------");
				current--;
		}
		 
	}
}
static TaskHandle_t xHandle;

static void btn_back_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(event == LV_EVENT_CLICKED) {
        lv_obj_t * par = lv_obj_get_parent(btn);
        lv_obj_del(par);
		
         
        lv_label_set_text(label_menu,"MENU");
        lv_obj_align(label_menu,scr_tft,LV_ALIGN_CENTER, 0 ,0);
        // if(list)
        // {
        //     lv_obj_del(list);
        // }
        
		vTaskDelete(xHandle);
		if(mp3->isRunning())			mp3->stop();
		if(mp3_current)	lv_obj_del(mp3_current);
		if(mp3_next)	lv_obj_del(mp3_next);
		if(mp3_prev)	lv_obj_del(mp3_prev);
		if(label_vol)   lv_obj_del(label_vol);

        eink_scene_ready=false;
        eink_flash_ready=false;


        // lv_task_del(task);
    }
}

static void read_content(const char *path, uint8_t *filecount); 
// static void music_loop(lv_task_t * task);
static void music_loop(void *para);
void music_create(lv_obj_t *obj, lv_event_t event)
{
	 
	if(event==LV_EVENT_CLICKED)
    {



		
		 


		//eink
		scr= lv_obj_create(scr_eink,NULL);
		lv_obj_set_size(scr, 176, 264);

		btn_back_create(scr,btn_back_event_cb);

		lv_obj_t *btn_play = lv_btn_create(scr,NULL);
		lv_obj_set_event_cb(btn_play,play_event);
		lv_obj_set_size(btn_play,50,50);

		lv_obj_t *label_play=lv_label_create(btn_play,NULL);
		lv_label_set_text(label_play,LV_SYMBOL_PLAY);



		lv_obj_t *btn_next = lv_btn_create(scr,btn_play);
		lv_obj_set_event_cb(btn_next,next_event);
		lv_obj_t *label_next=lv_label_create(btn_next,NULL);
		lv_label_set_text(label_next,LV_SYMBOL_NEXT);

		lv_obj_t *btn_prev = lv_btn_create(scr,btn_play);
		lv_obj_set_event_cb(btn_prev,prev_event);
		lv_obj_t *label_prev=lv_label_create(btn_prev,NULL);
		lv_label_set_text(label_prev,LV_SYMBOL_PREV);

		lv_obj_t *btn_vdown = lv_btn_create(scr,btn_play);
		lv_obj_set_event_cb(btn_vdown,voldown_event);
		lv_obj_t *label_vdown=lv_label_create(btn_vdown,NULL);
		lv_label_set_text(label_vdown,LV_SYMBOL_VOLUME_MID);

		lv_obj_t *btn_vup = lv_btn_create(scr,btn_play);
		lv_obj_set_event_cb(btn_vup,volup_event);
		lv_obj_t *label_vup=lv_label_create(btn_vup,NULL);
		lv_label_set_text(label_vup,LV_SYMBOL_VOLUME_MAX);


		lv_obj_align(btn_play,scr,LV_ALIGN_CENTER, 0, -20);
		lv_obj_align(btn_next,btn_play,LV_ALIGN_OUT_RIGHT_MID, 10, 0);
		lv_obj_align(btn_prev,btn_play,LV_ALIGN_OUT_LEFT_MID, -10, 0);

		lv_obj_align(btn_vup,btn_play,LV_ALIGN_OUT_TOP_MID, 0, -10);
		lv_obj_align(btn_vdown,btn_play,LV_ALIGN_OUT_BOTTOM_MID, 0, 10);


		eink_scene_ready=false;
        eink_flash_ready=false;


		//tft

		lv_label_set_text(label_menu,""); 


		musicfiles_cnt=0;

		File root = SD.open("/music");
		printDirectory(root,0);

		 mp3_current = lv_label_create(scr_tft,NULL);
		static lv_style_t style_current;
		lv_style_copy(&style_current,&lv_style_plain_color);
		style_current.text.color = LV_COLOR_MAKE(0x0f,0xff,0x0f);
		style_current.text.font = &lv_font_roboto_22;
		lv_label_set_style(mp3_current,LV_LABEL_STYLE_MAIN,&style_current);

		lv_label_set_text(mp3_current,musicfiles[0]);
		Serial.println(musicfiles[0]);

		lv_obj_align(mp3_current,scr_tft,LV_ALIGN_CENTER,0,0);

		 mp3_next = lv_label_create(scr_tft,NULL);
		static lv_style_t style_next;
		lv_style_copy(&style_next,&lv_style_plain_color);
		style_next.text.color = LV_COLOR_MAKE(0x7f,0x9f,0x0f);
		style_next.text.font = &lv_font_unscii_8;
		lv_label_set_style(mp3_next,LV_LABEL_STYLE_MAIN,&style_next);
		lv_label_set_text(mp3_next,musicfiles[1]);
		Serial.println(musicfiles[1]);
		lv_obj_align(mp3_next,mp3_current,LV_ALIGN_OUT_BOTTOM_MID,0,0);
		


		 mp3_prev = lv_label_create(scr_tft,mp3_next);
		lv_label_set_text(mp3_prev,"");
		lv_obj_align(mp3_prev,mp3_current,LV_ALIGN_OUT_TOP_MID,0,0);

		for(uint8_t i=0;i<musicfiles_cnt;i++)
		{
			Serial.println(musicfiles[i]);
		}



		label_vol = lv_label_create(scr_tft,NULL);
		char buffer_vol[4];
		snprintf(buffer_vol,sizeof(buffer_vol),"%d",volume);
		lv_label_set_text(label_vol,buffer_vol);
		lv_obj_align(label_vol,scr_tft,LV_ALIGN_IN_TOP_RIGHT,0,0);


 
		// lv_obj_t *btn_1=lv_list_add_btn(list,LV_SYMBOL_AUDIO,"sdksjdksjk.mp3");
		// 				lv_list_add_btn(list,LV_SYMBOL_AUDIO,"sds.mp3");
		// 				lv_list_add_btn(list,LV_SYMBOL_AUDIO,"aasderwws.mp3");
		// 				lv_list_add_btn(list,LV_SYMBOL_AUDIO,"123.mp3");
		// 				lv_list_add_btn(list,LV_SYMBOL_AUDIO,"sdksjsdsdsdsddsksjk.mp3");
		// 				lv_list_add_btn(list,LV_SYMBOL_AUDIO,"dsfdsf.mp3");

		// lv_list_set_btn_selected(list,btn_1);

		// lv_obj_t *label = lv_label_create(scr_tft,NULL);
		// lv_label_set_text(label,"Music Player");
		// lv_obj_set_pos(label,0,0);

				//AC101 INIT
		Serial.printf("Connect to AC101 codec... ");
		while (not ac.begin(IIC_DATA, IIC_CLK))
		{
			Serial.printf("Failed!\n");
			delay(1000);
		}
		Serial.printf("OK\n");

		ac.SetVolumeSpeaker(volume);
		ac.SetVolumeHeadphone(volume);
		io.digitalWrite0(1,1);
	//  ac.DumpRegisters();

		// Enable amplifier
		// pinMode(GPIO_PA_EN, OUTPUT);
		// digitalWrite(GPIO_PA_EN, HIGH);
		

		// Configure keys on ESP32 Audio Kit board
		// pinMode(PIN_PLAY, INPUT_PULLUP);
		// pinMode(PIN_VOL_UP, INPUT_PULLUP);
		// pinMode(PIN_VOL_DOWN, INPUT_PULLUP);

		// Create audio source from progmem, enable I2S output,
		// configure I2S pins to matchn the board and create ringtone generator.
		// file = new AudioFileSourcePROGMEM( song, strlen_P(song) );
		// out = new AudioOutputI2S();
		// out->SetPinout(IIS_SCLK /*bclkPin*/, IIS_LCLK /*wclkPin*/, IIS_DSIN /*doutPin*/);
		// rtttl = new AudioGeneratorRTTTL();
		// file = new AudioFileSourceSD("/music/1.MP3");
		// out = new AudioOutputI2S();
		// out->SetPinout(IIS_SCLK /*bclkPin*/, IIS_LCLK /*wclkPin*/, IIS_DSIN /*doutPin*/);
		// mp3 = new AudioGeneratorMP3();
		// mp3->begin(file, out);
		// Serial.printf("Use KEY4 to play, KEY5/KEY6 for volume Up/Down\n");
		// lv_task_t *task = lv_task_create(music_loop, 500, LV_TASK_PRIO_MID, NULL);
		// lv_task_set_period(task,100);
		out = new AudioOutputI2S();
	out->SetPinout(IIS_SCLK /*bclkPin*/, IIS_LCLK /*wclkPin*/, IIS_DSIN /*doutPin*/);
	mp3 = new AudioGeneratorMP3();
		 xTaskCreatePinnedToCore(
                                    music_loop
                                    ,  "music_loop"   // A name just for humans
                                    ,  1024*5  // This stack size can be checked & adjusted by reading the Stack Highwater
                                    ,  NULL
                                    ,  3  // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
                                    ,  &xHandle 
                                    ,  1);


	}

}

static void music_loop(void *para)
{
	
	delay(1000);
		
	while(1)
	{
		if (mp3->isRunning()) 
		{
			if (!mp3->loop()) mp3->stop(); 
		} 
		else 
		{
			Serial.printf("MP3 done\n");
			delay(1000);
		}
		delay(5);
	}  
}

// static void music_loop(lv_task_t * task)
// {
//   if (mp3->isRunning()) {
//     if (!mp3->loop()) mp3->stop(); 
//   } else {
//     Serial.printf("MP3 done\n");
//     delay(1000);
//   }
// }

// void loop_while()
// {
// 	bool updateVolume = false;

// 	if (pressed(PIN_PLAY) && !(rtttl->isRunning()))
// 	{
// 		// Start playing
// 		Serial.printf("Start playing\n");
// 		file->seek(0, SEEK_SET);
// 		rtttl->begin(file, out);
// 		updateVolume = true;
// 	}

// 	if (rtttl->isRunning())
// 	{
// 		if (!rtttl->loop())
// 		{
// 			rtttl->stop();
// 			// Last note seems to loop after stop.
// 			// To silence also set volume to 0.
// 			ac.SetVolumeSpeaker(0);
// 			ac.SetVolumeHeadphone(0);
// 		}
// 	}

// 	if (pressed(PIN_VOL_UP))
// 	{
// 		if (volume <= (63-volume_step))
// 		{
// 			// Increase volume
// 			volume += volume_step;
// 			updateVolume = true;
// 		} 
// 	}
// 	if (pressed(PIN_VOL_DOWN))
// 	{
// 		if (volume >= volume_step)
// 		{
// 			// Decrease volume
// 			volume -= volume_step;
// 			updateVolume = true;
// 		} 
// 	}
// 	if (updateVolume)
// 	{
// 		// Volume change requested
// 		Serial.printf("Volume %d\n", volume);
// 		ac.SetVolumeSpeaker(volume);
// 		ac.SetVolumeHeadphone(volume);
// 	}
// }

static void read_content(const char *path, uint8_t *filecount)
{
    // char nextpath[100];
    // struct dirent *de;
    // *filecount = 0;
    // DIR *dir = opendir(path);
    // while (1) {
    //     de = readdir(dir);
    //     if (!de) {
    //         break;
    //     } else if (de->d_type == DT_REG) {
    //         if (strstr(de->d_name, ".mp3") || strstr(de->d_name, ".MP3")) {
    //             sprintf(directory[*filecount], "%s/%s", path, de->d_name);
    //             printf("%s\n", directory[*filecount]);
    //             if ((*filecount)++ >= MAX_PLAY_FILE_NUM) {
    //                 break;
    //             }
    //         }
    //     } else if (de->d_type == DT_DIR) {
    //         sprintf(nextpath, "%s/%s", path, de->d_name);
    //         read_content(nextpath, filecount);
    //     }
    // }
    // closedir(dir);


	File root = SD.open("/music");
	printDirectory(root,0);
	

}

static void printDirectory(File dir, int numTabs) {
	
   while(true) {
     
     File entry =  dir.openNextFile();
     if (! entry) {
       // no more files
       break;
     }
     for (uint8_t i=0; i<numTabs; i++) {
       Serial.print('\t');
     }
     Serial.print(entry.name());
	 if (strstr(entry.name(), ".mp3") || strstr(entry.name(), ".MP3"))
	 {
		 
		memcpy(&musicfiles[musicfiles_cnt][0],entry.name(),20);
		musicfiles_cnt++;
		Serial.printf("\r\n%d\r\n",musicfiles_cnt);  
		Serial.println(musicfiles[musicfiles_cnt]);  
		 
	 }
     if (entry.isDirectory()) {
       Serial.println("/");
       printDirectory(entry, numTabs+1);
     } else {
       // files have sizes, directories do not
       Serial.print("\t\t");
       Serial.println(entry.size(), DEC);
     }
     entry.close();
   }
}